"""
流量监控服务实现
"""
import time
import traceback
from typing import List, Dict, Any, Optional
from PyQt5.QtCore import QTimer

from app.services.flow_monitor_service import IFlowMonitorService
from app.services.base_service import BaseService
from app.services.service_locator import ServiceLocator
from app.services.config_service import IConfigService
from app.utils.logger import Logger
from app.services.welcome_strategy_handler import WelcomeStrategyHandler


class FlowMonitorService(BaseService, IFlowMonitorService):
    """流量监控服务实现"""
    
    def __init__(self):
        super().__init__()
        self.logger = Logger.get_logger("flow_monitor_service")
        
        # 待处理用户队列
        self.pending_users = []
        
        # 用户进入时间戳列表（用于滑动窗口）
        self.user_timestamps = []
        
        # 当前流量等级
        self.current_flow_level = "low"  # 初始为低流量
        
        # 上一统计周期的用户数
        self.last_period_count = 0
        
        # 统计计时器
        self.timer = None
        
        # 是否正在监控
        self.is_monitoring = False
        
        # 上次处理时间
        self.last_process_time = 0
        
        # 获取配置服务
        self.config_service = ServiceLocator.get(IConfigService)
        
        # 初始化配置项变量
        self.enabled = self.config_service.get("flow_welcome", {}).get("enabled", True)
        self.period = self.config_service.get("flow_welcome", {}).get("period", 30)
        self.low_threshold = self.config_service.get("flow_welcome", {}).get("low_threshold", 5)
        self.high_threshold = self.config_service.get("flow_welcome", {}).get("high_threshold", 15)
        self.trigger_ratio = self.config_service.get("flow_welcome", {}).get("trigger_ratio", 0.5)
        
        self.logger.info("流量监控服务已初始化")
        
    def start_monitoring(self):
        """开始监控"""
        if self.is_monitoring:
            return
        
        # 确保使用最新配置
        try:
            # 仅更新当前对象的配置属性，不调用 reload_config 以避免递归调用
            config_service = ServiceLocator.get(IConfigService)
            if config_service:
                self.enabled = config_service.get("flow_welcome", {}).get("enabled", True)
                self.period = config_service.get("flow_welcome", {}).get("period", 30)
                self.low_threshold = config_service.get("flow_welcome", {}).get("low_threshold", 5)
                self.high_threshold = config_service.get("flow_welcome", {}).get("high_threshold", 15)
                self.trigger_ratio = config_service.get("flow_welcome", {}).get("trigger_ratio", 0.5)
                self.logger.info("已更新流量监控服务配置参数")
        except Exception as e:
            self.logger.error(f"更新流量监控服务配置参数失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            
        self.is_monitoring = True
        self.last_process_time = time.time()
        
        # 启动定时器，使用对象的 period 属性
        self.timer = QTimer()
        self.timer.timeout.connect(self._on_timer_triggered)
        self.timer.start(self.period * 1000)  # 毫秒
        
        self.logger.info(f"流量监控服务已启动，定时周期: {self.period}秒")
        
    def stop_monitoring(self):
        """停止监控"""
        if not self.is_monitoring:
            return
            
        self.is_monitoring = False
        
        # 停止定时器
        if self.timer:
            self.timer.stop()
            self.timer = None
            
        self.logger.info("流量监控服务已停止")
        
    def add_user(self, username: str):
        """
        添加用户到待处理队列并更新滑动窗口统计
        
        如果满足触发条件，会立即处理队列
        """
        if not self.is_monitoring:
            self.logger.info(f"流量监控服务未开启，跳过处理用户: {username}")
            return
            
        # 检查流量欢迎功能是否启用
        if not self.enabled:
            self.logger.debug(f"流量欢迎功能已禁用，跳过处理用户: {username}")
            return
            
        # 获取当前时间
        current_time = time.time()
        
        # 添加到待处理队列
        self.pending_users.append(username)
        self.logger.debug(f"已将用户 {username} 添加到待处理队列，当前队列长度: {len(self.pending_users)}")
        
        # 添加时间戳到滑动窗口
        self.user_timestamps.append(current_time)
        self.logger.debug(f"已添加时间戳到滑动窗口，当前窗口长度: {len(self.user_timestamps)}")
        
        # 清理滑动窗口中过期的记录
        old_len = len(self.user_timestamps)
        self._clean_sliding_window(current_time)
        new_len = len(self.user_timestamps)
        if old_len != new_len:
            self.logger.debug(f"已清理滑动窗口中过期的记录，从 {old_len} 条减少到 {new_len} 条")
        
        # 检查是否需要立即触发处理
        self._check_immediate_trigger(current_time)
        
    def get_current_flow_level(self) -> str:
        """获取当前流量等级"""
        return self.current_flow_level
        
    def get_last_period_count(self) -> int:
        """获取上一统计周期的用户数"""
        return self.last_period_count
        
    def configure(self, config: Dict[str, Any]) -> None:
        """
        配置流量监控服务
        
        @param config: 配置字典，可包含以下键：
            - enabled: 是否启用流量欢迎功能
            - period: 统计周期（秒）
            - low_threshold: 低流量阈值
            - high_threshold: 高流量阈值
            - trigger_ratio: 触发比例
        """
        self.logger.info(f"更新流量监控服务配置: {config}")
        
        # 保存配置
        if "period" in config:
            self.period = config["period"]
        if "low_threshold" in config:
            self.low_threshold = config["low_threshold"]
        if "high_threshold" in config:
            self.high_threshold = config["high_threshold"]
        if "trigger_ratio" in config:
            self.trigger_ratio = config["trigger_ratio"]
        
        # 如果启用状态发生变化
        if "enabled" in config:
            enabled = config["enabled"]
            self.enabled = enabled
            
            # 已启用 -> 已启用：重新配置定时器
            if enabled and self.is_monitoring and self.timer:
                # 停止当前定时器
                self.timer.stop()
                # 使用新周期创建定时器
                self.timer = QTimer()
                self.timer.timeout.connect(self._on_timer_triggered)
                self.timer.start(self.period * 1000)  # 转换为毫秒
                self.logger.info(f"已重新配置定时器，周期: {self.period}秒")
                
            # 未启用 -> 已启用：启动服务
            elif enabled and not self.is_monitoring:
                self.start_monitoring()
                self.logger.info("流量监控已启用")
                
            # 已启用 -> 未启用：停止服务
            elif not enabled and self.is_monitoring:
                self.stop_monitoring()
                self.logger.info("流量监控已禁用")
        
        # 如果统计周期发生变化且正在监控
        elif "period" in config and self.is_monitoring and self.timer:
            # 重启定时器
            self.timer.stop()
            self.timer = QTimer()
            self.timer.timeout.connect(self._on_timer_triggered)
            self.timer.start(self.period * 1000)  # 转换为毫秒
            self.logger.info(f"已更新定时器周期: {self.period}秒")
            
        # 其他配置项不需要立即处理，会在下次处理时使用新配置
        self.logger.info("流量监控服务配置已更新")
        
    def reload_config(self):
        """
        重新加载配置并立即应用
        该方法确保无论服务当前状态如何，都会根据最新配置调整
        
        @return: 是否成功重载配置
        """
        # 获取配置服务
        config_service = ServiceLocator.get(IConfigService)
        if not config_service:
            self.logger.error("无法获取配置服务，跳过重载配置")
            return False
            
        try:
            # 获取最新配置
            flow_welcome_config = config_service.get("flow_welcome", {})
            enabled = flow_welcome_config.get("enabled", False)
            period = flow_welcome_config.get("period", 30)
            low_threshold = flow_welcome_config.get("low_threshold", 5)
            high_threshold = flow_welcome_config.get("high_threshold", 15)
            trigger_ratio = flow_welcome_config.get("trigger_ratio", 0.5)
            
            # 日志记录当前配置
            self.logger.info(f"重载流量欢迎配置: 启用={enabled}, 周期={period}秒, "
                            f"低流量阈值={low_threshold}, 高流量阈值={high_threshold}, "
                            f"触发比例={trigger_ratio}")
            
            # 直接更新对象属性
            old_enabled = self.enabled
            old_period = self.period
            
            self.enabled = enabled
            self.period = period
            self.low_threshold = low_threshold
            self.high_threshold = high_threshold
            self.trigger_ratio = trigger_ratio
            
            # 准备配置字典
            config = {
                "enabled": enabled,
                "period": period,
                "low_threshold": low_threshold,
                "high_threshold": high_threshold,
                "trigger_ratio": trigger_ratio
            }
            
            # 调用 configure 方法应用配置
            self.configure(config)
            
            return True
            
        except Exception as e:
            self.logger.error(f"重载配置失败: {str(e)}")
            self.logger.error(traceback.format_exc())
            return False
        
    def _clean_sliding_window(self, current_time):
        """清理滑动窗口中超过统计周期的数据"""
        # 计算窗口开始时间
        window_start = current_time - self.period
        
        # 移除窗口外的时间戳
        while self.user_timestamps and self.user_timestamps[0] < window_start:
            self.user_timestamps.pop(0)
            
    def _check_immediate_trigger(self, current_time):
        """检查是否需要立即触发处理"""
        # 如果距离上次处理时间太短，不触发
        min_interval = 5  # 最小处理间隔5秒
        if current_time - self.last_process_time < min_interval:
            return
            
        # 计算触发阈值
        trigger_threshold = int(self.high_threshold * self.trigger_ratio)
        
        # 获取当前滑动窗口内的用户数
        current_count = len(self.user_timestamps)
        
        # 如果达到触发阈值且有待处理用户，立即触发处理
        if current_count >= trigger_threshold and self.pending_users:
            self.logger.info(f"检测到短时间内用户激增({current_count}人)，立即触发处理")
            self._process_queue()
            
    def _on_timer_triggered(self):
        """定时器触发处理"""
        if not self.is_monitoring:
            return
            
        self.logger.debug("定时器触发流量检测")
        self._process_queue()
        
    def _process_queue(self):
        """处理待处理队列"""
        # 记录处理时间
        self.last_process_time = time.time()
        
        # 获取当前用户数
        current_count = len(self.user_timestamps)
        self.last_period_count = current_count
        self.logger.info(f"处理队列，当前周期用户数: {current_count}")
        
        # 更新流量等级
        old_level = self.current_flow_level
        self._update_flow_level(current_count)
        if old_level != self.current_flow_level:
            self.logger.info(f"流量等级已从 {old_level} 变更为 {self.current_flow_level}")
        else:
            self.logger.debug(f"流量等级保持不变: {self.current_flow_level}")
        
        # 如果没有待处理用户，直接返回
        if not self.pending_users:
            self.logger.debug("没有待处理用户，跳过处理")
            return
            
        # 获取配置服务
        config_service = ServiceLocator.get(IConfigService)
        if not config_service:
            self.logger.error("无法获取配置服务，跳过处理")
            return
            
        config_path = config_service.get("app.config_path", "")
        if not config_path:
            self.logger.error("配置路径为空，跳过处理")
            return
            
        # 创建欢迎策略处理器
        welcome_handler = WelcomeStrategyHandler(config_path)
        
        self.logger.debug(f"开始处理用户队列，流量等级: {self.current_flow_level}, 队列长度: {len(self.pending_users)}")
        
        # 处理用户
        processed_count = welcome_handler.handle_users(self.pending_users, self.current_flow_level)
        
        self.logger.info(f"处理了 {processed_count}/{len(self.pending_users)} 个用户，当前流量等级: {self.current_flow_level}")
        
        # 清空待处理队列
        pending_count = len(self.pending_users)
        self.pending_users = []
        self.logger.debug(f"已清空待处理队列，原队列长度: {pending_count}")
        
    def _update_flow_level(self, user_count):
        """
        根据用户数量更新流量等级
        
        @param user_count: 用户数量
        """
        # 判断流量等级
        if user_count < self.low_threshold:
            new_level = "low"
        elif user_count > self.high_threshold:
            new_level = "high"
        else:
            new_level = "medium"
            
        # 如果流量等级发生变化，记录日志
        if new_level != self.current_flow_level:
            self.logger.info(f"流量等级从 {self.current_flow_level} 变为 {new_level}，当前用户数: {user_count}")
            
        # 更新流量等级
        self.current_flow_level = new_level 